package com.qf.forumproject.shiro;


import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.ShiroHttpSession;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.List;

/**
*shiro 配置类
 */

@Configuration
@EnableConfigurationProperties(QfShiroProperties.class)
public class ShiroConfig {


    @Autowired
    QfShiroProperties qfShiroProperties;

    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager webSecurityManager){

        final ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();

        // 设置 securitymanager
        shiroFilterFactoryBean.setSecurityManager(webSecurityManager);

        // 配置哪些url需要登录
        final HashMap<String, String> hashMap = new HashMap<>();
//
//        // 配置公共资源，无需认证即可访问
//        hashMap.put("/user/login","anon");
//        hashMap.put("/user/ajaxlogin","anon");
//        hashMap.put("/user/register","anon");
//        hashMap.put("/register.html","anon");
//
//        hashMap.put("/home.html","user"); // 让/home.html路径在rememberme状态下可以被访问到
//
//        // authc是shiro的一个过滤器的名字
//        hashMap.put("/**","authc");

        final List<String> anonList = qfShiroProperties.getAnonList();
        anonList.forEach(url->hashMap.put(url,"anon"));


        final List<String> authcList = qfShiroProperties.getAuthcList();
        for (String s : authcList) {
            hashMap.put(s,"authc");
        }

        final List<String> userList = qfShiroProperties.getUserList();
        userList.forEach(url->hashMap.put(url,"user"));


        shiroFilterFactoryBean.setFilterChainDefinitionMap(hashMap);
        // 设置登录页url
        shiroFilterFactoryBean.setLoginUrl("/login.html");


        return shiroFilterFactoryBean;


    }

    @Bean
    public DefaultWebSecurityManager webSecurityManager(CustomRealm customRealm){


        final DefaultWebSecurityManager defaultSecurityManager = new DefaultWebSecurityManager();

        //1. Realm
        defaultSecurityManager.setRealm(customRealm);

        //2. RememberMeManager
        defaultSecurityManager.setRememberMeManager(cookieRememberMeManager());

        //3. SessionManager
        defaultSecurityManager.setSessionManager(sessionManager());

        return defaultSecurityManager;

    }


    @Bean
    public HashedCredentialsMatcher hashedCredentialsMatcher(){

        // 创建 Hash凭证匹配器
        final HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();

        // 设置算法类型
        hashedCredentialsMatcher.setHashAlgorithmName(qfShiroProperties.getHashAlgorithmName());

        // 设置hash次数
        hashedCredentialsMatcher.setHashIterations(qfShiroProperties.getHashIterations());

        return hashedCredentialsMatcher;
    }

    @Bean
    public EhCacheManager ehCacheManager(){

        return new EhCacheManager();

    }

    // 创建CookieRememberMeManager
    @Bean
    public CookieRememberMeManager cookieRememberMeManager(){
        CookieRememberMeManager rememberMeManager=new CookieRememberMeManager();
        SimpleCookie simpleCookie=new SimpleCookie(qfShiroProperties.getRememberMeCookiename());
        simpleCookie.setMaxAge(qfShiroProperties.getRemeberMeMaxAge());
        // 设置 使用cookie的 samesite属性为 none
        simpleCookie.setSameSite(qfShiroProperties.getRememberMeSameSite());
        rememberMeManager.setCookie(simpleCookie);
        return rememberMeManager;
    }


    // 解决 重定向url后面带 jsessionid导致的报错
    @Bean
    public DefaultWebSessionManager sessionManager(){
        final DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();

        final SimpleCookie simpleCookie = new SimpleCookie(ShiroHttpSession.DEFAULT_SESSION_ID_NAME);
        // 允许返回的cookie被js代码访问
        simpleCookie.setHttpOnly(false);
        // 设置 使用cookie的 samesite属性为 none
        simpleCookie.setSameSite(qfShiroProperties.getRememberMeSameSite());
        sessionManager.setSessionIdCookie(simpleCookie);
        // 解决 路径后面带分号和 jsessionid的问题
        sessionManager.setSessionIdUrlRewritingEnabled(false);
        sessionManager.setSessionIdCookieEnabled(true);

        return sessionManager;
    }

}
